import { AfterViewInit, Component, ElementRef, OnDestroy, ViewChild } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Dnd } from '@antv/x6-plugin-dnd';
import { MessageService } from 'primeng/api';
import { MonitorBoardNode } from "src/components/scenarios/nodes/MonitorBoardNode";
import { Logger } from 'src/service/logger';
import { CellType } from '../../enums';
import { GraphConfigService } from '../../graph-config.service';
import { NodeConfig, ScenarioConfig } from '../../models';
import { PiplineNode } from '../../nodes/PiplineNode';
import { RgvNode } from '../../nodes/RgvNode';
import { SiteNode } from '../../nodes/SiteNode';
import { SrmNode } from '../../nodes/SrmNode';
import { ScenarioService } from '../../scenario.service';
import { ScenarioDesignGraphService } from '../scenario-design-graph.service';
import { ControlLibComponent } from './control-lib/control-lib.component';
import { MonitorBoardSettingComponent } from './monitor-board-setting/monitor-board-setting.component';
import { PiplineSettingComponent } from './pipline-setting/pipline-setting.component';
import { RgvSettingComponent } from './rgv-setting/rgv-setting.component';
import { ScenarioSettingComponent } from './scenario-setting/scenario-setting.component';
import { SiteSettingComponent } from './site-setting/site-setting.component';
import { SrmSettingComponent } from './srm-setting/srm-setting.component';

@Component({
  selector: 'app-scenario-design',
  templateUrl: './scenario-design.component.html',
  styleUrl: './scenario-design.component.scss',
  providers: [
    ScenarioDesignGraphService,
    GraphConfigService,
  ]
})
export class ScenarioDesignComponent implements AfterViewInit, OnDestroy {

  scenario!: ScenarioConfig;
  createNew: boolean = true;
  dnd?: Dnd;

  @ViewChild("graphContainer", { static: true })
  graphContainer!: ElementRef;

  @ViewChild("scenarioSetting", { static: true })
  scenarioSetting!: ScenarioSettingComponent;

  @ViewChild("piplineSetting", { static: true })
  piplineSetting!: PiplineSettingComponent;
  @ViewChild("siteSetting", { static: true })
  siteSetting!: SiteSettingComponent;
  @ViewChild("srmSetting", { static: true })
  srmSetting!: SrmSettingComponent;
  @ViewChild("boardSetting", { static: true })
  boardSetting!: MonitorBoardSettingComponent;
  @ViewChild("rgvSetting", { static: true })
  rgvSetting!: RgvSettingComponent;
  @ViewChild("ctrlLib", { static: true })
  ctrlLib!: ControlLibComponent;

  @ViewChild("fileInput", { static: false })
  fileInput!: ElementRef<HTMLInputElement>;

  get leftSidebarIcon() {
    return this.ctrlLib.isVisible ? 'pi pi-chevron-left' : 'pi pi-chevron-right';
  }

  constructor(
    private router: Router,
    private route: ActivatedRoute,
    private service: ScenarioService,
    private graphService: ScenarioDesignGraphService,
    private messageService: MessageService,
    private logger: Logger
  ) { }

  ngAfterViewInit(): void {
    this.graphService.nodeSelected.subscribe(node => {
      if (node instanceof PiplineNode) {
        this.piplineSetting.onEdit(node.data.cfg);
      } else if (node instanceof SiteNode) {
        this.siteSetting.onEdit(node.data.cfg);
      } else if (node instanceof SrmNode) {
        this.srmSetting.onEdit(node.data.cfg);
      } else if (node instanceof MonitorBoardNode) {
        this.boardSetting.onEdit(node.data.cfg);
      } else if (node instanceof RgvNode) {
        this.rgvSetting.onEdit(node.data.cfg);
      }
    });

    this.graphService.registerTypes();
    this.graphService.init(this.graphContainer.nativeElement);
    this.dnd = this.graphService.initDnd(this.ctrlLib.dndContainer.nativeElement);
    this.route.params.subscribe(params => {
      const { id } = params;
      if (id == 'new') {
        setTimeout(() => {
          this.scenario = {
            Name: "New Scenario",
            Lines: [],
            Srms: [],
            Boards: [],
            Rgvs: [],
          };
          this.createNew = true;
        });

      } else {
        this.service.get(id).subscribe(item => {
          this.scenario = item;
          this.scenario.Srms.forEach(srm => srm.Lane = srm.Lane ?? {
            MinColumn: 1,
            MaxColumn: 10,
            IsVisible: true,
            DoubleLine: false
          });
          this.createNew = false;
          this.graphService.loadScenario(item);
        });
      }
    });
  }

  ngOnDestroy(): void {
    this.graphService.unregisterTypes();
  }

  onShowLeftSidebar() {
    this.ctrlLib.toggle();
  }

  onLoadScenarioFile() {
    this.fileInput.nativeElement.click();
  }

  fileChangeEvent(event: Event) {
    const target: any = event.target;
    const file = target.files[0];
    this.logger.log(file);
    const reader = new FileReader();
    reader.onload = (e: any) => {
      try {
        const json = e.target.result;
        const item: ScenarioConfig = JSON.parse(json);
        item.Id = "";
        this.scenario = item;
        this.scenario.Srms.forEach(srm => srm.Lane = srm.Lane ?? {
          MinColumn: 1,
          MaxColumn: 10,
          IsVisible: true,
          DoubleLine: false
        });
        this.graphService.loadScenario(item);
      } catch (error) {
        this.messageService.add({ severity: 'warn', summary: '加载失败', detail: "文件格式错误，请重新选择文件！" });
      }
    };
    reader.readAsText(file, "UTF-8");
  }

  onSaveToCloud() {
    const { Id, Name } = this.scenario;
    const scenario: ScenarioConfig = {
      ...this.graphService.getScenario(),
      Id, Name
    };

    if (Id) {
      this.service.update(scenario).subscribe({
        next: item => {
          this.messageService.add({ severity: 'success', summary: '更新成功', });
          this.router.navigate(['/scenarios', 'design', item.Id]);
        },
        error: err => {
          const msgs: string[] = [];
          for (const key in err.error.errors) {
            if (Object.prototype.hasOwnProperty.call(err.error.errors, key)) {
              const msg = err.error.errors[key];
              msgs.push(`[${key}]:${msg}`);
            }
          }
          const detail = msgs.reduce((p, c) => `${p} \n${c};`, '');
          this.messageService.add({ severity: 'warn', summary: '保存失败', detail: detail });
        },
        complete: () => { }
      });
    }
    else {
      this.service.create(scenario).subscribe({
        next: item => {
          this.messageService.add({ severity: 'success', summary: '创建成功', });
          this.router.navigate(['/scenarios', 'design', item.Id]);
        },
        error: err => {
          const msgs: string[] = [];
          for (const key in err.error.errors) {
            if (Object.prototype.hasOwnProperty.call(err.error.errors, key)) {
              const msg = err.error.errors[key];
              msgs.push(`[${key}]:${msg}`);
            }
          }
          const detail = msgs.reduce((p, c) => p + '\n' + c, '');
          this.messageService.add({ severity: 'warn', summary: '创建失败', detail: detail });
        },
        complete: () => { }
      });
    }
  }

  onDownloadFromCloud() {
    this.service.get(this.scenario.Id!).subscribe({
      next: (res) => {
        const fileName = `${this.scenario.Name}.json`;
        const blob = new Blob([JSON.stringify(res, null, 2)], { type: 'application/json' });
        exportExcelFile(blob, fileName);
      }
    });
  }

  onEditScenario() {
    this.scenarioSetting?.onEdit(this.scenario);
  }

  startDrag(e: MouseEvent) {
    const target = e.currentTarget as HTMLElement;
    const type: CellType = <CellType>target.getAttribute("data-type")!;
    const data = this.graphService.getMetaFromType(type);
    const node = this.graphService.createNode(data);
    this.dnd!.start(node, e);
  }

  onEditScenarioComplate() {
  }

  onEditComplate(item: NodeConfig) {
    this.graphService.updateScenarioNode(item);
  }

  onRunScenario() {
    if (!this.createNew) {
      this.router.navigate(['/kanban', 'monitor', this.scenario.Id]);
    }
  }

  get canResetViewport() {
    const key = `View${this.scenario?.Id}`;
    const json = localStorage.getItem(key);
    if (json) {
      return true;
    }
    return false;
  }
  onResetViewport() {
    this.graphService.clearViewport();
  }
}

export function exportExcelFile(blob: Blob, fileName: string) {
  var objectUrl = URL.createObjectURL(blob);
  var a = document.createElement('a');
  document.body.appendChild(a);
  a.setAttribute('style', 'display:none');
  a.setAttribute('href', objectUrl);
  a.setAttribute('download', fileName);
  a.click();
  document.body.removeChild(a);
  URL.revokeObjectURL(objectUrl);
}